#pragma once

/*异步工作器类
    1:异步工作使用双缓冲的思想
    外界将任务添加到输入缓冲区中,异步线程对处理缓冲区的数据处理,若处理缓冲区没数据,则交换

*/
#include "Buffer.hpp"
#include <mutex>
#include <condition_variable>
#include <functional>
#include <thread>
#include <atomic>

namespace log
{
    enum class LooperType
    {
        SAFE,
        UNSAFE
    };
    using func_t = std::function<void(Buffer &)>;
    class AsyncLooper
    {
    public:
        using ptr = std::shared_ptr<AsyncLooper>;
        AsyncLooper(func_t func, LooperType loopertype = LooperType::SAFE) : _func(func), _stop(false),
                                                                             _thread(std::thread(&AsyncLooper::threadEntry, this)),
                                                                             _looper_type(loopertype)
        {
        }
        ~AsyncLooper()
        {
            stop();
        }
        void Push(const char *data, size_t len)
        {
            if (_stop == true)
                return;
            // 加锁保护缓冲区
            std::unique_lock<std::mutex> lock(_mtx);
            // 如果缓冲区的剩余数据能够写才往下进行,否则阻塞等待
            if (_looper_type == LooperType::SAFE)
                _pro_con_var.wait(lock, [&]()
                                  { return _pro_buf.WriteAbleSize() >= len; });
            _pro_buf.Push(data, len);

            _con_con_var.notify_one(); // 唤醒消费者
        }
        void stop()
        {
            _stop = true;
            _con_con_var.notify_all();
            _thread.join();
        }

    private:
        void threadEntry() // 线程入口函数
        {
            while (1)
            {
                {
                    std::unique_lock<std::mutex> lock(_mtx);
                    if(_stop==true&&_pro_buf.empty()) return;
                    // 如果数据缓冲区不为空或者异步工作器停止,则交换缓冲区
                    _con_con_var.wait(lock, [&]()
                                      { return !_pro_buf.empty() || _stop; });
                    _con_buf.Swap(_pro_buf);
                    // 完成对数据的处理
                    if (_looper_type == LooperType::SAFE)
                        _pro_con_var.notify_all();
                }
                _func(_con_buf);
                // 重置缓冲区
                _con_buf.reset();
            }
        }

    private:
        Buffer _pro_buf;
        Buffer _con_buf;
        std::mutex _mtx;
        std::condition_variable _pro_con_var;
        std::condition_variable _con_con_var;
        func_t _func; // 外界传入对消费缓冲区内数据进行处理的接口
        std::atomic<bool> _stop;
        std::thread _thread;
        LooperType _looper_type;
    };
}
